package com.antdesignbackend.backend.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.antdesignbackend.backend.common.CalendarDate;
import com.antdesignbackend.backend.common.IpUtil;
import com.antdesignbackend.backend.config.WebConfig;
import com.antdesignbackend.backend.config.WxMaConfiguration;
import com.antdesignbackend.backend.entity.*;
import com.antdesignbackend.backend.entity.entityVo.OrderInfoVo;
import com.antdesignbackend.backend.entity.entityVo.OrderShopVo;
import com.antdesignbackend.backend.entity.entityVo.ShopOrderVo;
import com.antdesignbackend.backend.entity.entityVo.WxPayMpOrderResultVO;
import com.antdesignbackend.backend.service.*;
import com.antdesignbackend.backend.util.HttpRequest;
import com.antdesignbackend.backend.util.PayUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@RestController
@RequestMapping("/pay")
@AllArgsConstructor
public class WxPayController {

    private WxPayService wxPayService;
    @Autowired
    private InterfaceController interfaceController;
    @Autowired
    private IRoomService roomService;
    @Autowired
    UserService userService;
    @Autowired
    IAppointmentService appointmentService;
    @Autowired
    MiddlecommandService middlecommandService;
    @Autowired
    RegistorderService registorderService;
    @Autowired
    RegistorderController registorderController;
    @Autowired
    EventService eventService;
    @Autowired
    UserRolesService userRolesService;
    @Autowired
    OrderService orderService;
    @Autowired
    SubscriptionService subscriptionService;
    @Autowired
    GoodsService goodsService;
    @Autowired
    AddressService addressService;
    @Autowired
    ShopOrderService shopOrderService;
    @Autowired
    ShopOrderItemService shopOrderItemService;


    @PostMapping("/unifiedOrder")
    public WxPayMpOrderResultVO unifiedOrder(@RequestBody OrderInfoVo orderInfoVo,HttpServletRequest requests) throws WxPayException, WxErrorException, ParseException {
        int shopId = orderInfoVo.getShopId();
        int roomId = orderInfoVo.getRoomId();
        boolean b = false;Double fee=0.0;
        double amount = orderInfoVo.getAmount().doubleValue();
        String startTime = orderInfoVo.getStartTime();
        String endTime = orderInfoVo.getEndTime();
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        boolean valid = true;//1.校验时间点内是否可预约；2.校验金额是否正确
        valid = interfaceController.IsAppoint(roomId,startTime,endTime);
        Room entity = roomService.getById(roomId);
        Double time=0.0;
        if(valid){
            long mins = 0;
            if(startTime.contains("00:00:00") && endTime.contains("24:00:00")){
                mins=1440;
            }else {
                mins = CalendarDate.dateDiff(startTime,endTime,"min");
            }
            //mins = CalendarDate.dateDiff(startTime,endTime,"min");
            Double min= Double.valueOf(mins);
            Double cy=60.0;
            fee= entity.getPrice()*(min/cy);
            time=min/cy;
            if(Double.doubleToLongBits(amount)!=Double.doubleToLongBits(fee)){
                valid = false;
            }
        }
        if(!valid){
            payResult.setCode(1);
            payResult.setMsg("不可能预订");
            return payResult;
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(this.wxPayService.getConfig().getAppId());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(orderInfoVo.getCode());
        String orderNumner = interfaceController.paymentID()+"_xcx";
        String clientIp = IpUtil.getRemoteIp(requests);
        String openId = session.getOpenid();
        //计入流水
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DateFormat dfdate = new SimpleDateFormat("yyyy-MM-dd");
        String startHHmm=startTime.substring(11,16).replace(":","");
        String endHHmm=endTime.substring(11,16).replace(":","");
        QueryWrapper<Users> wrapper =new QueryWrapper<Users>();
        wrapper.eq("openId",openId);
        List<Users> datalist= userService.search(wrapper);
        Appointment data=new Appointment();
        data.setStartTime(df.parse(startTime));
        data.setEndTime(df.parse(endTime));
        data.setCreateTime(new Date());
        data.setPrice(entity.getPrice());
        data.setRoomId(roomId);
        data.setShopId(entity.getShopId());
        data.setAppointDate(dfdate.parse(startTime));
        data.setStartInt(Integer.valueOf(startHHmm));
        data.setEndInt(Integer.valueOf(endHHmm));
        data.setIsMessage(0);
        data.setEvaluateScore(0);
        if(datalist.size()>0){
            data.setClientName(datalist.get(0).getUserName());
            data.setClientPhone(datalist.get(0).getPhone());
            data.setUserId(datalist.get(0).getUserID());
        }
        data.setIsMessageAdmin(0);
        data.setStreamFlag(0);
        data.setState(0);
        Double cstime=3.0;Double yktime=4.0;Double yktime2=24.0;
        if(entity.getRoomType().equals("茶室") && time.equals(cstime)){
            fee=108.0;
            orderInfoVo.setAmount(BigDecimal.valueOf(108.0));
        }
        if(entity.getRoomType().equals("影咖") && time.equals(yktime)){
            fee=168.0;
            orderInfoVo.setAmount(BigDecimal.valueOf(168.0));
        }
        if(entity.getRoomType().equals("影咖") && time.equals(yktime2)){
            fee=298.0;
            orderInfoVo.setAmount(BigDecimal.valueOf(298.0));
        }
        data.setAmount(fee);
        data.setTypes(2);
        data.setWeChat(openId);
        data.setOrderNumber(orderNumner);
        b=appointmentService.save(data);
        //如果orderVo保存成功
        if(b){
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            request.setOutTradeNo(orderNumner);
            request.setAppid(this.wxPayService.getConfig().getAppId());
            request.setSpbillCreateIp(clientIp);
            request.setBody("叁元空间小程序支付");
            request.setOpenid(openId);
            request.setNotifyUrl("https://www.3y-space.com/pay/notify");
            request.setTotalFee(new BigDecimal(orderInfoVo.getAmount().doubleValue()*10*10).intValue());//注意调整
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            request.setAttach(shopId+"@"+roomId);
            WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);

            String signType = WxPayConstants.SignType.MD5;
            payResult.setCode(0);
            payResult.setAppId(result.getAppid());
            payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            payResult.setNonceStr(result.getNonceStr());
            payResult.setPackageValue("prepay_id=" + result.getPrepayId());
            payResult.setSignType(signType);
            payResult.setPrepayId(result.getPrepayId());
            // 二次签名
            payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
        }
        return payResult;
    }

    private String createSign(WxPayMpOrderResultVO p, String mchKey) {
        String tosstr = "appId="+p.getAppId()+"&nonceStr="+p.getNonceStr()+"&package="+p.getPackageValue()
            +"&signType=MD5&timeStamp="+p.getTimeStamp()+"&key=" + mchKey;
        return DigestUtils.md5Hex(tosstr).toUpperCase();
    }

    @RequestMapping(value = "/notify")
    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        System.out.println("接收到的报文：" + notityXml);

        Map map = PayUtil.doXMLParse(notityXml);

        String returnCode = (String) map.get("return_code");
        if("SUCCESS".equals(returnCode)){
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String sign = PayUtil.sign(validStr, this.wxPayService.getConfig().getMchKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名
            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了

            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if(sign.equals(map.get("sign"))){
                // 得到返回的参数
                // 这边我上面也说过了  同理   需要什么参数  直接通过map.get获取   参数列表我上面也列举了
                String openid = (String) map.get("openid");
                String transaction_id = (String) map.get("transaction_id");
                String orderNumberMain = (String) map.get("out_trade_no");

                /**回调逻辑代码编写*/
                QueryWrapper<Appointment> wrapper =new QueryWrapper<Appointment>();
                wrapper.eq("orderNumber",orderNumberMain);
                Appointment appointment=appointmentService.getBaseMapper().selectOne(wrapper);
                appointment.setState(1);
                appointment.setPaymentTime(new Date());
                appointmentService.updateById(appointment);
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                System.out.println("微信支付回调失败!签名不一致");
            }
        }else{
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        System.out.println(resXml);
        System.out.println("微信支付回调数据结束");

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }
    //续费功能
    @PostMapping("/renewal")
    public WxPayMpOrderResultVO renewal(@RequestBody OrderInfoVo orderInfoVo,HttpServletRequest requests) throws WxPayException, WxErrorException, ParseException {
        boolean b = false;Double fee=0.0;
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        double amount = orderInfoVo.getAmount().doubleValue();
        String startTime = orderInfoVo.getStartTime();
        String endTime = orderInfoVo.getEndTime();
        String attributionOrder = orderInfoVo.getAttributionOrder();
        //查出对应的订单
        QueryWrapper<Appointment> appwrapper =new QueryWrapper<Appointment>();
        appwrapper.eq("orderNumber",attributionOrder);
        Appointment applist= appointmentService.getBaseMapper().selectOne(appwrapper);
        int shopId = applist.getShopId();
        int roomId = applist.getRoomId();
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        boolean valid = false;boolean validb = false;//1.校验时间点内是否可续费；2.校验金额是否正确
        String appEndTime=df.format(applist.getEndTime());
        if(appEndTime.equals(startTime)){
            valid = interfaceController.isRenewal(roomId,startTime,endTime);
            validb=valid;
            if(!validb){
                payResult.setCode(1);
                payResult.setMsg("后续有人预约，不可续费");
                return payResult;
            }
        }
        Room entity = roomService.getById(roomId);
        if(valid){
            long mins = 0;
            mins = CalendarDate.dateDiff(startTime,endTime,"min");
            Double min= Double.valueOf(mins);
            Double cy=60.0;
            fee= entity.getPrice()*(min/cy);
            if(Double.doubleToLongBits(amount)!=Double.doubleToLongBits(fee)){
                payResult.setCode(1);
                payResult.setMsg("续费金额有误");
                return payResult;
            }
        }
        if(!valid){
            payResult.setCode(1);
            payResult.setMsg("续费开始时间不是订单结束时间");
            return payResult;
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(this.wxPayService.getConfig().getAppId());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(orderInfoVo.getCode());
        String orderNumner = interfaceController.paymentID()+"_xcx";
        String clientIp = IpUtil.getRemoteIp(requests);
        String openId = session.getOpenid();
        //计入流水
        DateFormat dfdate = new SimpleDateFormat("yyyy-MM-dd");
        String startHHmm=startTime.substring(11,16).replace(":","");
        String endHHmm=endTime.substring(11,16).replace(":","");
        QueryWrapper<Users> wrapper =new QueryWrapper<Users>();
        wrapper.eq("openId",openId);
        List<Users> datalist= userService.search(wrapper);
        Appointment data=new Appointment();
        data.setStartTime(df.parse(startTime));
        data.setEndTime(df.parse(endTime));
        data.setCreateTime(new Date());
        data.setPrice(entity.getPrice());
        data.setRoomId(roomId);
        data.setParentAppId(applist.getId());
        data.setShopId(entity.getShopId());
        data.setAppointDate(dfdate.parse(startTime));
        data.setStartInt(Integer.valueOf(startHHmm));
        data.setEndInt(Integer.valueOf(endHHmm));
        data.setIsMessage(0);
        data.setEvaluateScore(0);
        if(datalist.size()>0){
            data.setClientName(datalist.get(0).getUserName());
            data.setClientPhone(datalist.get(0).getPhone());
            data.setUserId(datalist.get(0).getUserID());
        }
        data.setIsMessageAdmin(0);
        data.setStreamFlag(0);
        data.setState(0);
        data.setAmount(fee);
        data.setTypes(2);
        data.setWeChat(openId);
        data.setOrderNumber(orderNumner);
        b=appointmentService.save(data);
        //如果orderVo保存成功
        if(b){
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            request.setOutTradeNo(orderNumner);
            request.setAppid(this.wxPayService.getConfig().getAppId());
            request.setSpbillCreateIp(clientIp);
            request.setBody("叁元空间小程序支付");
            request.setOpenid(openId);
            request.setNotifyUrl("https://www.3y-space.com/pay/renotify");
            request.setTotalFee(new BigDecimal(orderInfoVo.getAmount().doubleValue()*10*10).intValue());//注意调整
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            request.setAttach(shopId+"@"+roomId);
            WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);
            String signType = WxPayConstants.SignType.MD5;
            payResult.setCode(0);
            payResult.setAppId(result.getAppid());
            payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            payResult.setNonceStr(result.getNonceStr());
            payResult.setPackageValue("prepay_id=" + result.getPrepayId());
            payResult.setSignType(signType);
            payResult.setPrepayId(result.getPrepayId());
            // 二次签名
            payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
        }
        return payResult;
    }
    //续费功能回调
    @RequestMapping(value = "/renotify")
    public void rewxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        System.out.println("接收到的报文：" + notityXml);
        Map map = PayUtil.doXMLParse(notityXml);
        String returnCode = (String) map.get("return_code");
        if("SUCCESS".equals(returnCode)){
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String sign = PayUtil.sign(validStr, this.wxPayService.getConfig().getMchKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名
            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了

            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if(sign.equals(map.get("sign"))){
                // 得到返回的参数
                // 这边我上面也说过了  同理   需要什么参数  直接通过map.get获取   参数列表我上面也列举了
                String openid = (String) map.get("openid");
                String transaction_id = (String) map.get("transaction_id");
                String orderNumberMain = (String) map.get("out_trade_no");

                /**回调逻辑代码编写*/
                QueryWrapper<Appointment> wrapper =new QueryWrapper<Appointment>();
                wrapper.eq("orderNumber",orderNumberMain);
                Appointment appointment=appointmentService.getBaseMapper().selectOne(wrapper);
                appointment.setState(1);
                appointment.setPaymentTime(new Date());
                appointmentService.updateById(appointment);
                //延长房间供电
                Date start=appointment.getStartTime();
                Date end=appointment.getEndTime();
                Long diff=(end.getTime()-start.getTime())/60/1000;
                Integer minute=diff.intValue();
                QueryWrapper<Middlecommand> middWrapper =new QueryWrapper<Middlecommand>();
                middWrapper.eq("status",0);
                middWrapper.eq("roomId",appointment.getRoomId());
                middWrapper.gt("actionTime",new Date());
                List<Middlecommand> middList = middlecommandService.getBaseMapper().selectList(middWrapper);
                for(Middlecommand midd:middList){
                    Date actionTime=midd.getActionTime();
                    Calendar calendars = Calendar.getInstance();
                    calendars.setTime(actionTime);
                    calendars.add(Calendar.MINUTE, +minute);
                    midd.setActionTime(calendars.getTime());
                    middlecommandService.updateById(midd);
                }
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                System.out.println("微信支付回调失败!签名不一致");
            }
        }else{
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        System.out.println(resXml);
        System.out.println("微信支付回调数据结束");

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }
    //待支付订单发起支付
    @PostMapping("/defrayOrder")
    public WxPayMpOrderResultVO defrayOrder(@RequestBody OrderInfoVo orderInfoVo,HttpServletRequest requests) throws WxPayException, WxErrorException, ParseException {
        String attributionOrder = orderInfoVo.getAttributionOrder();
        //查出对应的订单
        QueryWrapper<Appointment> appwrapper =new QueryWrapper<Appointment>();
        appwrapper.eq("orderNumber",attributionOrder);
        Appointment applist= appointmentService.getBaseMapper().selectOne(appwrapper);
        int shopId = applist.getShopId();
        int roomId = applist.getRoomId();
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        final WxMaService wxService = WxMaConfiguration.getMaService(this.wxPayService.getConfig().getAppId());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(orderInfoVo.getCode());
        String clientIp = IpUtil.getRemoteIp(requests);
        String openId = session.getOpenid();
        //如果orderVo保存成功
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setOutTradeNo(attributionOrder);
        request.setAppid(this.wxPayService.getConfig().getAppId());
        request.setSpbillCreateIp(clientIp);
        request.setBody("叁元空间小程序支付");
        request.setOpenid(openId);
        request.setNotifyUrl("https://www.3y-space.com/pay/notify");
        request.setTotalFee(new BigDecimal(applist.getAmount().doubleValue()*10*10).intValue());//注意调整
        request.setTradeType(WxPayConstants.TradeType.JSAPI);
        request.setAttach(shopId+"@"+roomId);
        WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);
        String signType = WxPayConstants.SignType.MD5;
        payResult.setCode(0);
        payResult.setAppId(result.getAppid());
        payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
        payResult.setNonceStr(result.getNonceStr());
        payResult.setPackageValue("prepay_id=" + result.getPrepayId());
        payResult.setSignType(signType);
        payResult.setPrepayId(result.getPrepayId());
        // 二次签名
        payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
        return payResult;
    }
    //开通会员支付
    @PostMapping("/memberOrder")
    public WxPayMpOrderResultVO memberOrder(@RequestBody OrderInfoVo orderInfoVo,HttpServletRequest requests) throws WxPayException, WxErrorException, ParseException {
        Boolean b=false;
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        final WxMaService wxService = WxMaConfiguration.getMaService(this.wxPayService.getConfig().getAppId());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(orderInfoVo.getCode());
        String orderNumner = interfaceController.paymentID()+"_member";
        String clientIp = IpUtil.getRemoteIp(requests);
        String openId = session.getOpenid();
        //查询用户
        QueryWrapper<Users> userWrapper =new QueryWrapper<Users>();
        userWrapper.eq("openId",openId);
        Users users=userService.getBaseMapper().selectOne(userWrapper);
        //查询活动
        QueryWrapper<Event> wrapper =new QueryWrapper<Event>();
        wrapper.eq("eventId",1);
        Event event=eventService.getBaseMapper().selectOne(wrapper);
        //存入预订单
        Registorder data=new Registorder();
        data.setCreateTime(new Date());
        data.setState(0);
        data.setClientName(users.getUserName());
        data.setClientPhone(users.getPhone());
        data.setFlag(0);
        data.setOrderNumber(orderNumner);
        data.setAmount(event.getEventAmount());
        data.setOderFlag(1);
        data.setUserId(users.getUserID());
        b=registorderService.save(data);
        //如果orderVo保存成功
        if(b){
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            request.setOutTradeNo(orderNumner);
            request.setAppid(this.wxPayService.getConfig().getAppId());
            request.setSpbillCreateIp(clientIp);
            request.setBody("叁元空间小程序支付");
            request.setOpenid(openId);
            request.setNotifyUrl("https://www.3y-space.com/pay/memberNotify");
            request.setTotalFee(new BigDecimal(event.getEventAmount().doubleValue()*10*10).intValue());//注意调整
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            //request.setAttach(shopId+"@"+roomId);
            WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);

            String signType = WxPayConstants.SignType.MD5;
            payResult.setCode(0);
            payResult.setAppId(result.getAppid());
            payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            payResult.setNonceStr(result.getNonceStr());
            payResult.setPackageValue("prepay_id=" + result.getPrepayId());
            payResult.setSignType(signType);
            payResult.setPrepayId(result.getPrepayId());
            // 二次签名
            payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
        }
        return payResult;
    }
    //开通会员回调
    @RequestMapping(value = "/memberNotify")
    public void memberwxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        System.out.println("接收到的报文：" + notityXml);
        Map map = PayUtil.doXMLParse(notityXml);
        String returnCode = (String) map.get("return_code");
        if("SUCCESS".equals(returnCode)){
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String sign = PayUtil.sign(validStr, this.wxPayService.getConfig().getMchKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名
            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了

            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if(sign.equals(map.get("sign"))){
                // 得到返回的参数
                // 这边我上面也说过了  同理   需要什么参数  直接通过map.get获取   参数列表我上面也列举了
                String openid = (String) map.get("openid");
                String transaction_id = (String) map.get("transaction_id");
                String orderNumberMain = (String) map.get("out_trade_no");

                /**回调逻辑代码编写*/
                QueryWrapper<Registorder> wrapper =new QueryWrapper<Registorder>();
                wrapper.eq("orderNumber",orderNumberMain);
                Registorder data=registorderService.getBaseMapper().selectOne(wrapper);
                data.setState(1);
                registorderService.updateById(data);
                //查询活动
                QueryWrapper<Event> queryWrapper =new QueryWrapper<Event>();
                queryWrapper.eq("eventId",1);
                Event event=eventService.getOne(queryWrapper);
                //认证会员
                Users users=userService.getById(data.getUserId());
                users.setTypes(1);
                users.setUserType(5);
                Double amount=users.getFrozenAmount()+event.getAmount();
                Double shopAmount=users.getShopAmount()+event.getAmount();
                users.setFrozenAmount(amount);
                users.setShopAmount(shopAmount);
                userService.updateById(users);
                //修改角色权限表
                QueryWrapper<UserRoles> rolesQueryWrapper =new QueryWrapper<UserRoles>();
                rolesQueryWrapper.eq("userID",data.getUserId());
                UserRoles userRoles=new UserRoles();
                userRoles.setUserID(data.getUserId());
                userRoles.setRoleID(5);
                userRolesService.update(userRoles,rolesQueryWrapper);
                //会员分成
                registorderController.charg(data.getUserId(),orderNumberMain);
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                System.out.println("微信支付回调失败!签名不一致");
            }
        }else{
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        System.out.println(resXml);
        System.out.println("微信支付回调数据结束");

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }
    //开通合伙人支付
    @PostMapping("/partnerOrder")
    public WxPayMpOrderResultVO partnerOrder(@RequestBody OrderInfoVo orderInfoVo,HttpServletRequest requests) throws WxPayException, WxErrorException, ParseException {
        Boolean b=false;
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        final WxMaService wxService = WxMaConfiguration.getMaService(this.wxPayService.getConfig().getAppId());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(orderInfoVo.getCode());
        String orderNumner = interfaceController.paymentID()+"_partner";
        String clientIp = IpUtil.getRemoteIp(requests);
        String openId = session.getOpenid();
        //查询用户
        QueryWrapper<Users> userWrapper =new QueryWrapper<Users>();
        userWrapper.eq("openId",openId);
        Users users=userService.getBaseMapper().selectOne(userWrapper);
        if(users.getMemberId()!=null){
            return payResult;
        }
        //查询活动
        QueryWrapper<Event> wrapper =new QueryWrapper<Event>();
        wrapper.eq("eventId",2);
        Event event=eventService.getBaseMapper().selectOne(wrapper);
        //存入预订单
        Registorder data=new Registorder();
        data.setCreateTime(new Date());
        data.setState(0);
        data.setClientName(users.getUserName());
        data.setClientPhone(users.getPhone());
        data.setFlag(0);
        data.setOrderNumber(orderNumner);
        data.setAmount(event.getEventAmount());
        data.setOderFlag(2);
        data.setUserId(users.getUserID());
        b=registorderService.save(data);
        //如果orderVo保存成功
        if(b){
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            request.setOutTradeNo(orderNumner);
            request.setAppid(this.wxPayService.getConfig().getAppId());
            request.setSpbillCreateIp(clientIp);
            request.setBody("叁元空间小程序支付");
            request.setOpenid(openId);
            request.setNotifyUrl("https://www.3y-space.com/pay/partnerNotify");
            request.setTotalFee(new BigDecimal(event.getEventAmount().doubleValue()*10*10).intValue());//注意调整
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            //request.setAttach(shopId+"@"+roomId);
            WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);

            String signType = WxPayConstants.SignType.MD5;
            payResult.setCode(0);
            payResult.setAppId(result.getAppid());
            payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            payResult.setNonceStr(result.getNonceStr());
            payResult.setPackageValue("prepay_id=" + result.getPrepayId());
            payResult.setSignType(signType);
            payResult.setPrepayId(result.getPrepayId());
            // 二次签名
            payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
        }
        return payResult;
    }
    //开通合伙人回调
    @RequestMapping(value = "/partnerNotify")
    public void partnerNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        System.out.println("接收到的报文：" + notityXml);
        Map map = PayUtil.doXMLParse(notityXml);
        String returnCode = (String) map.get("return_code");
        if("SUCCESS".equals(returnCode)){
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String sign = PayUtil.sign(validStr, this.wxPayService.getConfig().getMchKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名
            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了

            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if(sign.equals(map.get("sign"))){
                // 得到返回的参数
                // 这边我上面也说过了  同理   需要什么参数  直接通过map.get获取   参数列表我上面也列举了
                String openid = (String) map.get("openid");
                String transaction_id = (String) map.get("transaction_id");
                String orderNumberMain = (String) map.get("out_trade_no");

                /**回调逻辑代码编写*/
                QueryWrapper<Registorder> wrapper =new QueryWrapper<Registorder>();
                wrapper.eq("orderNumber",orderNumberMain);
                Registorder data=registorderService.getBaseMapper().selectOne(wrapper);
                data.setState(1);
                registorderService.updateById(data);
                //查询活动
                QueryWrapper<Event> queryWrapper =new QueryWrapper<Event>();
                queryWrapper.eq("eventId",1);
                Event event=eventService.getOne(queryWrapper);
                //认证合伙人
                Users users=userService.getById(data.getUserId());
                users.setTypes(1);
                users.setUserType(2);
                Double amount=users.getFrozenAmount()+event.getAmount();
                Double shopAmount=users.getShopAmount()+event.getAmount();
                users.setFrozenAmount(amount);
                users.setShopAmount(shopAmount);
                userService.updateById(users);
                //修改角色权限表
                QueryWrapper<UserRoles> rolesQueryWrapper =new QueryWrapper<UserRoles>();
                rolesQueryWrapper.eq("userID",data.getUserId());
                UserRoles userRoles=new UserRoles();
                userRoles.setUserID(data.getUserId());
                userRoles.setRoleID(2);
                userRolesService.update(userRoles,rolesQueryWrapper);
                //合伙人分成
                registorderController.chargPro(data.getUserId(),orderNumberMain);
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                System.out.println("微信支付回调失败!签名不一致");
            }
        }else{
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        System.out.println(resXml);
        System.out.println("微信支付回调数据结束");

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }
    //开通包月权益
    @PostMapping("/subscription")
    public WxPayMpOrderResultVO subscription(@RequestBody OrderInfoVo orderInfoVo,HttpServletRequest requests) throws WxPayException, WxErrorException, ParseException {
        Boolean b=false;
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        final WxMaService wxService = WxMaConfiguration.getMaService(this.wxPayService.getConfig().getAppId());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(orderInfoVo.getCode());
        String orderNumner = interfaceController.paymentID()+"_monthly";
        String clientIp = IpUtil.getRemoteIp(requests);
        String openId = session.getOpenid();
        //查询用户
        QueryWrapper<Users> userWrapper =new QueryWrapper<Users>();
        userWrapper.eq("openId",openId);
        Users users=userService.getBaseMapper().selectOne(userWrapper);
        //查询活动
        QueryWrapper<Event> wrapper =new QueryWrapper<Event>();
        wrapper.eq("eventId",79);
        Event event=eventService.getBaseMapper().selectOne(wrapper);
        Date starTime=new Date();
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(starTime);
        rightNow.add(Calendar.MONTH, 1);
        //存入预订单
        Subscription data=new Subscription();
        data.setStartTime(starTime);
        data.setState(0);
        data.setName(users.getUserName());
        data.setOrderNumber(orderNumner);
        data.setMoney(event.getEventAmount());
        data.setUserId(users.getUserID());
        data.setEndTime(rightNow.getTime());
        b=subscriptionService.save(data);
        //如果orderVo保存成功
        if(b){
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            request.setOutTradeNo(orderNumner);
            request.setAppid(this.wxPayService.getConfig().getAppId());
            request.setSpbillCreateIp(clientIp);
            request.setBody("叁元空间小程序支付");
            request.setOpenid(openId);
            request.setNotifyUrl("https://www.3y-space.com/pay/memberNotify");
            request.setTotalFee(new BigDecimal(event.getEventAmount().doubleValue()*10*10).intValue());//注意调整
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            //request.setAttach(shopId+"@"+roomId);
            WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);

            String signType = WxPayConstants.SignType.MD5;
            payResult.setCode(0);
            payResult.setAppId(result.getAppid());
            payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            payResult.setNonceStr(result.getNonceStr());
            payResult.setPackageValue("prepay_id=" + result.getPrepayId());
            payResult.setSignType(signType);
            payResult.setPrepayId(result.getPrepayId());
            // 二次签名
            payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
        }
        return payResult;
    }
    //开通包月回调
    @RequestMapping(value = "/monthlyNotify")
    public void monthlyNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        System.out.println("接收到的报文：" + notityXml);
        Map map = PayUtil.doXMLParse(notityXml);
        String returnCode = (String) map.get("return_code");
        if("SUCCESS".equals(returnCode)){
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String sign = PayUtil.sign(validStr, this.wxPayService.getConfig().getMchKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名
            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了

            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if(sign.equals(map.get("sign"))){
                // 得到返回的参数
                // 这边我上面也说过了  同理   需要什么参数  直接通过map.get获取   参数列表我上面也列举了
                String openid = (String) map.get("openid");
                String transaction_id = (String) map.get("transaction_id");
                String orderNumberMain = (String) map.get("out_trade_no");

                /**回调逻辑代码编写*/
                QueryWrapper<Subscription> wrapper =new QueryWrapper<Subscription>();
                wrapper.eq("orderNumber",orderNumberMain);
                Subscription data=subscriptionService.getBaseMapper().selectOne(wrapper);
                data.setState(1);
                subscriptionService.updateById(data);
                //包月会员开通
                Users users=userService.getById(data.getUserId());
                users.setIsMonthly(1);
                userService.updateById(users);
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                System.out.println("微信支付回调失败!签名不一致");
            }
        }else{
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        System.out.println(resXml);
        System.out.println("微信支付回调数据结束");

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }

    /**
     * 发起支付
     * @param
     * @return
     */
    @PostMapping("/payment")
    @ResponseBody
    public WxPayMpOrderResultVO pay(HttpServletRequest requests){
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        String orderNumber=interfaceController.paymentID()+"_sale_"+"1";
        try {
            //拼接统一下单地址参数
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            request.setAppid(this.wxPayService.getConfig().getAppId());
            request.setBody("售货柜支付");
            request.setOpenid("o5efn5fD52cfu1tUQgljcQc9PdQw");
            request.setOutTradeNo(orderNumber);
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            request.setSpbillCreateIp(IpUtil.getRemoteIp(requests));
            Double amount=10.0;
            request.setTotalFee(new BigDecimal(amount.doubleValue()*10*10).intValue());
            request.setNotifyUrl("https://www.3y-space.com/pay/notify");
            WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);
            String signType = WxPayConstants.SignType.MD5;
            payResult.setCode(0);
            payResult.setAppId(result.getAppid());
            payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            payResult.setNonceStr(result.getNonceStr());
            payResult.setPackageValue("prepay_id=" + result.getPrepayId());
            payResult.setSignType(signType);
            payResult.setPrepayId(result.getPrepayId());
            // 二次签名
            payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
            //log.warn("售货柜支付----------------------------"+payResult);
        }catch (Exception e){
            //log.error(e.getMessage());
        }
        return payResult;
    }
    /**
     * 发起支付
     * @param order
     * @return
     */
    /*@PostMapping("/payment")
    @ResponseBody
    public Map<String,String> pay(@RequestBody OrderInfoVo orderInfoVo,HttpServletRequest requests){
        //log.warn("售货柜支付1");
        Map<String, String> payMap = new HashMap<String, String>();
        InterfaceController interfaceController = new InterfaceController();
        String orderNumber=interfaceController.paymentID()+"_sale_"+orderInfoVo.getCabinetitemId();
        //通过openid找到userId
        QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openId","o5efn5bXzDjAcwedicjKCITF8w84");
        Users users = userService.getOne(queryWrapper);
        Integer userId = null;
        if (users != null){
            userId = users.getUserID();
        }
        try {
            order.setOrderNumber(orderNumber);
            order.setOpenId("o5efn5bXzDjAcwedicjKCITF8w84");
            order.setUserId(userId);
            order.setCreateTime(new Date());
            if (orderService.save(order)){
                //拼接统一下单地址参数
                // log.warn("售货柜支付2");
                Map<String, String> paraMap = new HashMap<String, String>();
                // log.warn("售货柜支付2+---");
                paraMap.put("appid", "wx204609f407036d11");
                paraMap.put("body", "售货柜支付");
                paraMap.put("mch_id", "1580823371");
                paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
                paraMap.put("openid", "o5efn5fD52cfu1tUQgljcQc9PdQw");
                paraMap.put("out_trade_no", orderNumber);//订单号
                String clientIp = IpUtil.getRemoteIp(requests);
                paraMap.put("spbill_create_ip", clientIp);
                paraMap.put("total_fee",new BigDecimal(order.getAmount().doubleValue()*10*10).intValue());
//                paraMap.put("trade_type", "JSAPI");
                paraMap.put("trade_type", "JSAPI");
                paraMap.put("notify_url","https://www.3y-space.com/pay/notify");// 此路径是微信服务器调用支付结果通知路径随意写
                String sign = WXPayUtil.generateSignature(paraMap, this.wxPayService.getConfig().getMchKey());
                //log.warn("售货柜支付2+---"+sign);
                paraMap.put("sign", sign);

                String xml = WXPayUtil.mapToXml(paraMap);

                // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
                String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

                String xmlStr = HttpRequest.sendPost(unifiedorder_url,xml);//发送post请求"统一下单接口"返回预支付id:prepay_id

                //log.warn("售货柜支付3");
                //log.warn("售货柜支付3+----"+xmlStr);
                //以下内容是返回前端页面的json数据
                String prepay_id = "";//预支付id
                if (xmlStr.indexOf("SUCCESS") != -1) {
                    Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                    prepay_id = (String) map.get("prepay_id");
                }

                payMap.put("appId", WebConfig.appid);
                payMap.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
                payMap.put("nonceStr", WXPayUtil.generateNonceStr());
                payMap.put("signType", "MD5");
                payMap.put("package", "prepay_id=" + prepay_id);
                String paySign = WXPayUtil.generateSignature(payMap, WebConfig.paternerKey);
                payMap.put("paySign", paySign);
                //log.warn("售货柜支付4");
            }
        }catch (Exception e){
            //log.error(e.getMessage());
        }
        return payMap;
    }
*/
    @PostMapping("/shopOrder")
    public WxPayMpOrderResultVO shopOrder(@RequestBody ShopOrderVo orderInfoVo, HttpServletRequest requests) throws WxPayException, WxErrorException, ParseException {
        Integer userId = orderInfoVo.getUserId();
        Integer addressId = orderInfoVo.getAddressId();
        List<OrderShopVo> itemList=orderInfoVo.getItemList();
        double amount = orderInfoVo.getAmount().doubleValue();
        boolean b = false;boolean c = false;Double fee=0.0;
        WxPayMpOrderResultVO payResult = new WxPayMpOrderResultVO();
        String orderNumner = interfaceController.paymentID()+"_sc";

        final WxMaService wxService = WxMaConfiguration.getMaService(this.wxPayService.getConfig().getAppId());
        WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(orderInfoVo.getCode());

        String clientIp = IpUtil.getRemoteIp(requests);
        String openId = session.getOpenid();
        //计入订单
        ShopOrder shopOrder=new ShopOrder();
        shopOrder.setOrderNo(orderNumner);
        shopOrder.setUserId(userId);
        shopOrder.setCreateTime(new Date());
        shopOrder.setPayState(0);
        shopOrder.setPayType(0);
        shopOrder.setOrderState(0);
        if(addressId!=null){
            Address address=addressService.getById(addressId);
            if(address!=null){
                shopOrder.setUserName(address.getUserName());
                shopOrder.setPhone(address.getPhone());
                shopOrder.setAddress(address.getAddress());
            }else {
                payResult.setCode(1);
                payResult.setMsg("收货地址信息有误");
                return payResult;
            }
        }
        b=shopOrderService.save(shopOrder);
        if(b){
            if(itemList.size()>0){
                Double allAmount=0.0;
                for(OrderShopVo shopVo:itemList){
                    ShopOrderItem shopOrderItem=new ShopOrderItem();
                    shopOrderItem.setOrderId(shopOrder.getId());
                    shopOrderItem.setGoodId(shopVo.getGoodId());
                    shopOrderItem.setNumber(shopVo.getNumber());
                    shopOrderItem.setCreateTime(new Date());
                    Goods goods=goodsService.getById(shopVo.getGoodId());
                    if(goods!=null){
                        shopOrderItem.setGoodName(goods.getName());
                        shopOrderItem.setAmount(goods.getAmount());
                        Double totalAmount=(goods.getAmount()*goods.getDiscount()+goods.getFreight()+goods.getSurcharge()
                                +goods.getOtherFees1()+goods.getOtherFees2())*shopVo.getNumber();
                        allAmount=allAmount+totalAmount;
                        shopOrderItem.setTotalAmount(totalAmount);
                        shopOrderItem.setImageUrl(goods.getImageUrl());
                        shopOrderItemService.save(shopOrderItem);
                    }else {
                        payResult.setCode(1);
                        payResult.setMsg("商品信息有误");
                        return payResult;
                    }
                }
                if(Double.doubleToLongBits(amount)!=Double.doubleToLongBits(allAmount)){
                    payResult.setCode(1);
                    payResult.setMsg("商品总价有误");
                    return payResult;
                }
                shopOrder.setTotalAmount(allAmount);
                c=shopOrderService.updateById(shopOrder);
            }
        }
        //如果orderVo保存成功
        if(c){
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            request.setOutTradeNo(orderNumner);
            request.setAppid(this.wxPayService.getConfig().getAppId());
            request.setSpbillCreateIp(clientIp);
            request.setBody("叁元空间小程序支付");
            request.setOpenid(openId);
            request.setNotifyUrl("https://www.3y-space.com/pay/shopOrderNotify");
            request.setTotalFee(new BigDecimal(orderInfoVo.getAmount().doubleValue()*10*10).intValue());//注意调整
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            request.setAttach(userId+"@"+addressId);
            WxPayUnifiedOrderResult result =  this.wxPayService.unifiedOrder(request);

            String signType = WxPayConstants.SignType.MD5;
            payResult.setCode(0);
            payResult.setAppId(result.getAppid());
            payResult.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
            payResult.setNonceStr(result.getNonceStr());
            payResult.setPackageValue("prepay_id=" + result.getPrepayId());
            payResult.setSignType(signType);
            payResult.setPrepayId(result.getPrepayId());
            // 二次签名
            payResult.setSign(createSign(payResult, this.wxPayService.getConfig().getMchKey()));
        }
        return payResult;
    }
    @RequestMapping(value = "/shopOrderNotify")
    public void shopOrderNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        System.out.println("接收到的报文：" + notityXml);

        Map map = PayUtil.doXMLParse(notityXml);

        String returnCode = (String) map.get("return_code");
        if("SUCCESS".equals(returnCode)){
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String validStr = PayUtil.createLinkString(validParams);//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
            String sign = PayUtil.sign(validStr, this.wxPayService.getConfig().getMchKey(), "utf-8").toUpperCase();//拼装生成服务器端验证的签名
            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了

            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            if(sign.equals(map.get("sign"))){
                // 得到返回的参数
                // 这边我上面也说过了  同理   需要什么参数  直接通过map.get获取   参数列表我上面也列举了
                String openid = (String) map.get("openid");
                String transaction_id = (String) map.get("transaction_id");
                String orderNumberMain = (String) map.get("out_trade_no");

                /**回调逻辑代码编写*/
                QueryWrapper<ShopOrder> wrapper =new QueryWrapper<ShopOrder>();
                wrapper.eq("orderNo",orderNumberMain);
                ShopOrder shopOrder=shopOrderService.getBaseMapper().selectOne(wrapper);
                shopOrder.setPayState(1);
                shopOrder.setPayTime(new Date());
                shopOrder.setOrderState(1);
                shopOrderService.updateById(shopOrder);
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                System.out.println("微信支付回调失败!签名不一致");
            }
        }else{
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        System.out.println(resXml);
        System.out.println("微信支付回调数据结束");

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }
}

